{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "be1936a1",
   "metadata": {},
   "source": [
    "# 基于昇思MindSpore+Orangepi AIpro的ResNet50图像分类\n",
    "\n",
    "功能：使用基于昇思MindSpore框架开发的ResNet50实现图片分类。  \n",
    "样例输入：原始图片。   \n",
    "样例输出：图片分类的结果。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "97f89a7a",
   "metadata": {},
   "source": [
    "# 前期准备\n",
    "\n",
    "* 基础镜像的样例目录中已包含转换后的om模型以及测试图片，如果直接运行，可跳过此步骤。如果需要重新转换模型，可以参考下面的步骤。\n",
    "* **建议在Linux服务器或者虚拟机转换该模型。**\n",
    "* 为了能进一步优化模型推理性能，我们需要将其转换为om模型进行使用；**转换指导详见全流程实验指导。**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4fc6880a",
   "metadata": {},
   "source": [
    "# 模型推理实现\n",
    "\n",
    "* 注意：本案例在离线推理的过程中可能会出现内存不足的问题，可以根据情况查看FAQ文档中的解决方案。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "82e7b4fc",
   "metadata": {},
   "source": [
    "### 1. 导入三方库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "234f0d2f",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import cv2\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "import acl\n",
    "import acllite_utils as utils\n",
    "import constants as const\n",
    "from acllite_imageproc import AclLiteImageProc\n",
    "from acllite_model import AclLiteModel\n",
    "from acllite_resource import resource_list\n",
    "\n",
    "import mindspore as ms\n",
    "import mindspore.dataset as ds\n",
    "from mindspore.dataset import vision"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "245196ca",
   "metadata": {},
   "source": [
    "### 2. 定义acllite资源初始化与去初始化类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "f5f2d3fe",
   "metadata": {},
   "outputs": [],
   "source": [
    "class AclLiteResource:\n",
    "    \"\"\"\n",
    "    AclLiteResource\n",
    "    \"\"\"\n",
    "    def __init__(self, device_id=0):\n",
    "        self.device_id = device_id\n",
    "        self.context = None\n",
    "        self.stream = None\n",
    "        self.run_mode = None\n",
    "        \n",
    "    def init(self):\n",
    "        \"\"\"\n",
    "        init resource\n",
    "        \"\"\"\n",
    "        print(\"init resource stage:\")\n",
    "        ret = acl.init()\n",
    "\n",
    "        ret = acl.rt.set_device(self.device_id)\n",
    "        utils.check_ret(\"acl.rt.set_device\", ret)\n",
    "\n",
    "        self.context, ret = acl.rt.create_context(self.device_id)\n",
    "        utils.check_ret(\"acl.rt.create_context\", ret)\n",
    "\n",
    "        self.stream, ret = acl.rt.create_stream()\n",
    "        utils.check_ret(\"acl.rt.create_stream\", ret)\n",
    "\n",
    "        self.run_mode, ret = acl.rt.get_run_mode()\n",
    "        utils.check_ret(\"acl.rt.get_run_mode\", ret)\n",
    "\n",
    "        print(\"Init resource success\")\n",
    "\n",
    "    def __del__(self):\n",
    "        print(\"acl resource release all resource\")\n",
    "        resource_list.destroy()\n",
    "        if self.stream:\n",
    "            print(\"acl resource release stream\")\n",
    "            acl.rt.destroy_stream(self.stream)\n",
    "\n",
    "        if self.context:\n",
    "            print(\"acl resource release context\")\n",
    "            acl.rt.destroy_context(self.context)\n",
    "\n",
    "        print(\"Reset acl device \", self.device_id)\n",
    "        acl.rt.reset_device(self.device_id)\n",
    "        print(\"Release acl resource success\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a7c6270b",
   "metadata": {},
   "source": [
    "### 3. 定义Resnet50类，包含前处理、推理等操作"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "824f39a0",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Resnet50(object):\n",
    "    \"\"\"\n",
    "    class for Resnet50\n",
    "    \"\"\"\n",
    "    def __init__(self, model_path, model_width, model_height):\n",
    "        self._model_path = model_path\n",
    "        self._model_width = model_width\n",
    "        self._model_height = model_height\n",
    "        self.device_id = 0\n",
    "        self._dvpp = None\n",
    "        self._model = None\n",
    "\n",
    "    def init(self):\n",
    "        \"\"\"\n",
    "        Initialize\n",
    "        \"\"\"\n",
    "        # 初始化dvpp\n",
    "        self._dvpp = AclLiteImageProc()\n",
    "\n",
    "        # 加载模型\n",
    "        self._model = AclLiteModel(self._model_path)\n",
    "        return const.SUCCESS\n",
    "    \n",
    "    @utils.display_time\n",
    "    # 定义数据预处理函数\n",
    "    def pre_process(self, input_path):\n",
    "        # 利用Cifar10Dataset接口读取测试数据\n",
    "        dataset_predict = ds.Cifar10Dataset(dataset_dir=input_path, shuffle=False)\n",
    "        # 对数据进行预处理操作：调整数据尺寸、归一化、标准化、调整通道顺序。\n",
    "        image_test = [\n",
    "            vision.Resize((32, 32)),\n",
    "            vision.Rescale(1.0 / 255.0, 0.0),\n",
    "            vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),\n",
    "            vision.HWC2CHW()\n",
    "                ]\n",
    "        dataset_predict = dataset_predict.map(image_test, 'image')\n",
    "        # 设置推理数据的batch\n",
    "        dataset_predict = dataset_predict.batch(4)\n",
    "\n",
    "        return dataset_predict\n",
    "    \n",
    "    @utils.display_time\n",
    "    def inference(self, input_path, dataset_predict1):\n",
    "        \"\"\"\n",
    "        model inference\n",
    "        \"\"\"\n",
    "        # 迭代读取数据\n",
    "        resized_image = next(dataset_predict1.create_dict_iterator())\n",
    "        images = resized_image[\"image\"]\n",
    "        labels = resized_image[\"label\"]\n",
    "        print(\"resized_image['label']: \", resized_image['label'])\n",
    "        result1 = ms.Tensor(resized_image['image'])\n",
    "        # 对数据进行推理\n",
    "        preds = self._model.execute([result1.asnumpy(), ])\n",
    "        \n",
    "        return images, labels, preds\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "efe2a06b",
   "metadata": {},
   "source": [
    "### 4. 构造主函数，串联整个代码逻辑"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "154ee4b3",
   "metadata": {},
   "outputs": [],
   "source": [
    "from download import download\n",
    "\n",
    "# 获取数据集\n",
    "dataset_url = \"https://modelers.cn/coderepo/web/v1/file/MindSpore-Lab/cluoud_obs/main/media/examples/mindspore-courses/orange-pi-mindspore/03-ResNet50/cifar-10-batches-bin.zip\"\n",
    "download(dataset_url, \"./datasets-cifar10-bin\", kind=\"zip\", replace=True)\n",
    "\n",
    "# 获取模型om文件\n",
    "model_url = \"https://modelers.cn/coderepo/web/v1/file/MindSpore-Lab/cluoud_obs/main/media/examples/mindspore-courses/orange-pi-mindspore/03-ResNet50/resnet50.zip\"\n",
    "download(model_url, \"./model\", kind=\"zip\", replace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "409c556a",
   "metadata": {},
   "outputs": [],
   "source": [
    "def main():\n",
    "\n",
    "    # 给定模型路径和输入模型的图片尺寸\n",
    "    MODEL_PATH = \"./model/resnet50.om\"\n",
    "    MODEL_WIDTH = 32\n",
    "    MODEL_HEIGHT = 32\n",
    "    # 初始化acl资源\n",
    "    acl_resource = AclLiteResource() \n",
    "    acl_resource.init()\n",
    "    \n",
    "    # 初始化 Resnet50 类\n",
    "    resnet50 = Resnet50(MODEL_PATH, MODEL_WIDTH, MODEL_HEIGHT)  # 构造模型对象\n",
    "    \n",
    "    # 初始化模型类变量\n",
    "    ret = resnet50.init()  \n",
    "    utils.check_ret(\"Resnet50.init \", ret)  \n",
    "    # 给定推理数据的路径\n",
    "    input_path = \"./datasets-cifar10-bin/cifar-10-batches-bin\"\n",
    "\n",
    "    print('===================')\n",
    "    # 调用数据预处理函数，对数据进行预处理\n",
    "    crop_and_paste_image = resnet50.pre_process(input_path)\n",
    "    \n",
    "    print(\"crop_and_paste_image: \", crop_and_paste_image)\n",
    "    # 进行推理\n",
    "    images, labels, result = resnet50.inference(input_path, crop_and_paste_image)\n",
    "    pred = np.argmax(result[0], axis=1)\n",
    "    print(\"pred: \", pred)\n",
    "    \n",
    "    classes = []\n",
    "\n",
    "    with open(input_path + \"/batches.meta.txt\", \"r\") as f:\n",
    "        for line in f:\n",
    "            line = line.rstrip()\n",
    "            if line:\n",
    "                classes.append(line)\n",
    "\n",
    "    # 显示图像及图像的预测值\n",
    "    plt.figure()\n",
    "    for i in range(4):\n",
    "        plt.subplot(2, 2, i + 1)\n",
    "        # 若预测正确，显示为蓝色；若预测错误，显示为红色\n",
    "        color = 'blue' if pred[i] == labels.asnumpy()[i] else 'red'\n",
    "        plt.title('predict:{}'.format(classes[pred[i]]), color=color)\n",
    "        picture_show = np.transpose(images.asnumpy()[i], (1, 2, 0))\n",
    "        mean = np.array([0.4914, 0.4822, 0.4465])\n",
    "        std = np.array([0.2023, 0.1994, 0.2010])\n",
    "        picture_show = std * picture_show + mean\n",
    "        picture_show = np.clip(picture_show, 0, 1)\n",
    "        plt.imshow(picture_show)\n",
    "        plt.axis('off')\n",
    "\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "00d10204",
   "metadata": {},
   "source": [
    "### 5. 运行\n",
    "运行完成后，会显示推理后的图片，如下所示。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "a5069cf3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "init resource stage:\n",
      "Init resource success\n",
      "Init model resource start...\n",
      "[AclLiteModel] create model output dataset:\n",
      "malloc output 0, size 160\n",
      "Create model output dataset success\n",
      "Init model resource success\n",
      "===================\n",
      "crop_and_paste_image:  <mindspore.dataset.engine.datasets.BatchDataset object at 0xe7ff3e2cd9d0>\n",
      "resized_image['label']:  [3 8 8 0]\n",
      "pred:  [3 8 8 0]\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "acl resource release all resource\n",
      "dvpp resource release success\n",
      "AclLiteModel release source success\n",
      "acl resource release stream\n",
      "acl resource release context\n",
      "Reset acl device  0\n",
      "Release acl resource success\n"
     ]
    }
   ],
   "source": [
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e2e907eb",
   "metadata": {},
   "source": [
    "# 样例总结\n",
    "\n",
    "我们来回顾一下以上代码，可以包括以下几个步骤：\n",
    "\n",
    "1. 初始化acl资源：在调用acl相关资源时，必须先初始化AscendCL，否则可能会导致后续系统内部资源初始化出错。  \n",
    "2. 推理：利用AclLiteModel.execute接口对图片进行推理。  \n",
    "3. 对推理结果进行后处理：包括两个步骤，即转换像素值值域以及将图片缩放到原图大小。  \n",
    "4. 可视化图片：利用plt将结果画出。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.19"
  },
  "vscode": {
   "interpreter": {
    "hash": "5d4380103ee16a53c08c2072b2cf7372aea12e3655e7cb36be2874465cdcb878"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
